MsgN("-- mdf_server.lua loaded")

include("player.lua")













MDF.Timer = 0
MDF.GameStarted = false

function MDF.GameTicker()
	if (!MDF.IsEnabled()) then return end

	if (!MDF.Timer) then MDF.Timer = 0 end

	if (MDF.Timer == 0) then
		MDF.GameStarted = false
		MDF.LowerWater()

		for _, ply in pairs(player.GetAll()) do
			ply:DropAll()
			ply:BuildTools()
			ply:PrintMessage( HUD_PRINTCENTER, "Start Build" )
		end

	elseif (MDF.Timer == MDF.BuildTime) then
		MDF.GameStarted = true

		for _, ply in pairs(player.GetAll()) do
			ply:DropAll()
			ply:Loadout()
			ply:PrintMessage( HUD_PRINTCENTER, "Flood!" )
		end
		
		MDF.WaterRaise()

	elseif (MDF.Timer == (MDF.BuildTime + MDF.FloodTime)) then

		for _, ply in pairs(player.GetAll()) do
			ply:DropAll()
			ply:PrintMessage( HUD_PRINTCENTER, "Flood Over! Water is lowering." )
		end

		MDF.LowerWater()

	elseif (MDF.Timer == (MDF.BuildTime + MDF.FloodTime + MDF.EndRoundTime)) then
		for _, ply in pairs(player.GetAll()) do
			ply:PrintMessage( HUD_PRINTCENTER, "Winner!" )
		end

		MDF.Timer = -1	--reset game
	end

	for _, ply in pairs( player.GetAll() ) do
		if (ply:WaterLevel() != 0) then
			ply:TakeDamage( math.random(1, 5) )
		end
	
		umsg.Start("MDF.GetInfo")
		umsg.Long( MDF.Timer )	--send timer value
		umsg.Float( ply:GetCash() )	--send timer value
		umsg.End()
	
	end
		


	MDF.Timer = (MDF.Timer + 1)
end




--create the timer for the rounds
timer.Destroy("MDF.GameTicker")
timer.Create("MDF.GameTicker", 1, 0, MDF.GameTicker)




function MDF.PlayerSpawn( ply )
	if (!MDF.IsEnabled()) then return end

	--set player health to 100
	ply:SetHealth(100)

	--set team
	ply:SetTeam(TEAM_NORMAL)

	if (MDF.GameStarted) then
		ply:Loadout()
	else
		ply:BuildTools()
	end
end

hook.Add("PlayerSpawn", "MDF.PlayerSpawn", MDF.PlayerSpawn)




function MDF.PlayerDeathThink( ply )
	if (!MDF.IsEnabled()) then return end

	--if game has started respawn player
	if (!MDF.GameStarted) then
		ply:Spawn()
		return true
	end

	--get alive players
	local players = table.Copy(team.GetPlayers(TEAM_NORMAL))

	--if no alive players exit
	if (!players || table.Count(players) == 0) then return end

	if ply:KeyPressed( IN_JUMP ) then
		if ply.Specatemode == OBS_MODE_CHASE then
			ply.Specatemode = OBS_MODE_IN_EYE
			ply:SetPos(players[ply.specid]:GetPos())
			ply:UnSpectate()
			ply:Spectate(ply.Specatemode)
			ply:SpectateEntity( players[ply.specid] )
		elseif ply.Specatemode == OBS_MODE_IN_EYE then
			ply.Specatemode = OBS_MODE_CHASE
			ply:SetPos(players[ply.specid]:GetPos())
			ply:UnSpectate()
			ply:Spectate(ply.Specatemode)
			ply:SpectateEntity( players[ply.specid] )
		end
	elseif ply:KeyPressed( IN_ATTACK ) then
		if !ply.specid then
			ply.specid = 1
		end
		ply.specid = ply.specid + 1

		if ply.specid > #players then
			ply.specid = 1
		end

		if (!players[ply.specid]) then return end

		ply:SetPos(players[ply.specid]:GetPos())
		ply:UnSpectate()
		ply:Spectate(ply.Specatemode)
		ply:SpectateEntity( players[ply.specid] )
	elseif ply:KeyPressed( IN_ATTACK2 ) then
		if !ply.specid then
			ply.specid = 1
		end
		ply.specid = ply.specid - 1

		if ply.specid <= 0 then
			ply.specid = #players
		end

		ply:SetPos(players[ply.specid]:GetPos())
		ply:UnSpectate()
		ply:Spectate(ply.Specatemode)
		ply:SpectateEntity( players[ply.specid] )
	end
	
	return true
end
hook.Add("PlayerDeathThink", "MDF.PlayerDeathThink", MDF.PlayerDeathThink)





function MDF.PlayerDisconnected( ply )
	if (!MDF.IsEnabled()) then return end
	
	--loop through all ents
	for _, ent in pairs(ents.GetAll()) do
		--check owner
		if (ent.Owner == ply) then
			ent:Remove()	--remove
			--self:CashRefundProp( ent )
		end
	end

	--loop through players
	for _, _ply in pairs(player.GetAll()) do
		--send message about the disconnected users props being cleaned up
		_ply:ChatPrint(_ply:Nick() .. "'s props have been cleaned up!")
	end

end
hook.Add("PlayerDisconnected", "MDF.PlayerDisconnected", MDF.PlayerDisconnected)


function MDF.PlayerSpawnedProp( ply, model, ent )
	if (!MDF.IsEnabled()) then return end
	
	--make sure prop is ok to spawn
	if (!table.HasValue(PList or {}, model)) then
		--remove since its not allowed
		ent:Remove()
	return end

	--set owner
	ent.Owner = ply
end
hook.Add("PlayerSpawnedProp", "MDF.PlayerSpawnedProp", MDF.PlayerSpawnedProp)










function MDF.SpawnProp( ply, model )
	if (!MDF.IsEnabled()) or (MDF.GameStarted) then return end
	if (!ply) or (!ply:IsValid()) or (!ply:IsPlayer()) then return end

	local propInfo = nil

	--check models
	for _model, _info in pairs(list.Get("FloodProps")) do
		--compare model strings
		if (_model == model) then
			propInfo = _info
			break --exit for
		end
	end

	--dont spawn a prop if the model is found
	if (!propInfo) then return end
	
	MsgN("propInfo:")
	PrintTable(propInfo)
	
	local tr = util.TraceLine(util.GetPlayerTrace( ply ))
	
	--if (!tr.Hit) then return end
	
	local ent = ents.Create( "mdf_base" )
	if ( !ent:IsValid() ) then return end

	ent:SetModel( model )
	ent:SetPos( tr.HitPos )
	ent:Spawn()
	ent:Activate()
	ent:SetPos( tr.HitPos - tr.HitNormal * ent:OBBMins().z )
	ent:SetAngles( tr.HitNormal:Angle() + Angle(90,0,0) )

	--get physics
	local phys = ent:GetPhysicsObject()

	--if physics is valid
	if phys:IsValid() then
		phys:EnableMotion(true)
		phys:Wake()
	end

	--save owner
	ent.Owner = ply


	--calcuate prop health
	local propHealth =  math.Clamp(propInfo.health, 0, 400)
	local propCost = propInfo.cost

	--make sure we have enough cash
	if (ply:GetCash() < propCost) then
		ent:Remove()	--remove ent since we dont have enough cash
		ply:ChatPrint("You do not have enough money for this!")	--let user know that they dont have enough cash
		return	--exit
	else
		--set prop health
		ent:SetHealth(propHealth)
		ent:SetMaxHealth(propHealth)

		--let the user know cash has been taken
		ply:ChatPrint("-$" .. tostring(propInfo.cost))

		ply:SpendCash( propCost )	--take cash
	end

	--save ent title
	ent:SetNWString("Title", "Prop\nHealth: \t " .. tostring(propHealth) .. "/" .. tostring(propHealth) .. "\nOwner: \t " .. string.Replace(ply:Name(), "\\", ""))

	--add prop to undo
	undo.Create("prop")
	undo.AddEntity( ent )
	undo.SetPlayer( ply )
	undo.Finish()
end

concommand.Add( "MDFSpawnProp", function(ply, cmd, arg) 
	if (!arg) or (!arg[1]) then return end
	MDF.SpawnProp( ply, arg[1] )
end )

--[[
concommand.Add( "MDFSpawnWeapon", function(ply, cmd, arg) 
	if (!arg) or (!arg[1]) then return end
	MDF.SpawnWeapon( ply, arg[1] )
end )
]]


function MDF.CanTool( ply, tr, tool)
	if (!MDF.IsEnabled()) then return end
	
	--cant use tool against world
	if tr.Entity:IsWorld() then
		return false
	--cant use tool against non-valid prop
	elseif !tr.Entity:IsValid() then
		return false
	--cant use tool against something thats not players unless player is admin
	elseif tr.Entity.Owner != py && !ply:IsAdmin() then
		return false
	end

	--returns true or false if the player can use the tool
	return table.HasValue(AllowedTools, tool)
end
hook.Add("CanTool", "MDF.CanTool", MDF.CanTool)

function MDF.PlayerShouldTakeDamage(victim, attacker)
	if (!MDF.IsEnabled()) then return end
	
	MsgN("PlayerShouldTakeDamage")
	
	return true --MDF.GameStarted
end
hook.Add("PlayerShouldTakeDamage", "MDF.PlayerShouldTakeDamage", MDF.PlayerShouldTakeDamage)

function MDF.EntityTakeDamage( ent, inflictor, attacker, amount, dmginfo  )
	if (!MDF.IsEnabled()) then return end
	if (ent:IsPlayer()) or (ent:IsWeapon()) or (ent:IsWorld()) then return true end

	--if flame reduce damage by half
	if (attacker:GetClass() == "entityflame") then
		dmginfo:ScaleDamage( (amount / 5) )
	else
		dmginfo:ScaleDamage( (amount / 2) )
	end

	--save ent health
	ent:SetHealth( ent:Health() - amount )

	--if health zero or below, remove ent
	if (ent:Health() <= 0) then
		--kill player
		if (ent:IsPlayer()) then
			ent:Kill()
		--remove ent
		else
			ent:Remove()
		end
	elseif (!ent:IsPlayer()) then
		--save ent health across the network
		ent:SetNWString("Title", "Prop\nHealth: \t " .. tostring(ent:Health()) .. "/" .. tostring(ent:GetMaxHealth()) .. "\nOwner: \t " .. string.Replace(ent.Owner:Name(), "\\", ""))
	end
end
hook.Add("EntityTakeDamage", "MDF.EntityTakeDamage", MDF.EntityTakeDamage)


function MDF.PlayerNoClip( ply )
	if (!MDF.IsEnabled()) then return end
	
	--cant noclip during game
	if (MDF.GameStarted)  then
		return false --cant noclip
	else
		return true
	end

end
hook.Add("PlayerNoClip", "MDF.PlayerNoClip", MDF.PlayerNoClip)





function MDF.WaterRaise()
	if (!MDF.IsEnabled()) then return end

	for _, ply in pairs( player.GetAll() ) do
		ply:UnfreezePhysicsObjects()
	end

	for _, ent in pairs(ents.FindByName("water")) do
		ent:Fire("Open","",0)
	end

	for _, ent in pairs( ents.GetAll() ) do
		local phys = ent:GetPhysicsObject()
		
		if (phys:IsValid()) then phys:Wake() end
	end
end

function MDF.LowerWater()
	if (!MDF.IsEnabled()) then return end
	
	--get all water ents
	for _, ent in pairs(ents.FindByName("water")) do
		--turn water off
		ent:Fire("Close","",0)
	end
end